package org.myabstract.graph.model.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.myabstract.graph.model.Graph;
import org.myabstract.graph.model.INodeType;
import org.myabstract.graph.model.Node;
import org.myabstract.graph.model.Reference;

public class GraphTests {

	private Node<INodeType> node1 = new Node<INodeType>(new Mock1NodeType());
	private Node<INodeType> node2 = new Node<INodeType>(new Mock2NodeType());
	private Node<INodeType> node3 = new Node<INodeType>(new Mock3NodeType());

	List<Node<INodeType>> nodeList = Graph.instance.getNodeList();

	@Before
	public void setUp() {

		nodeList = Graph.instance.getNodeList();

		// System.out.print("setup nodeList: "+nodeList.size());

		if (!nodeList.isEmpty())
			this.emptyGraphTest();

		// System.out.println("\tgraph: "+Graph.getNodeList().size());

	}

	public void emptyGraphTest() {
		nodeList = Graph.instance.getNodeList();

		for (int i = 0; i < nodeList.size(); i++) {
			Node<INodeType> node = nodeList.get(i);
			Graph.instance.removeNode(node);
		}
		nodeList = Graph.instance.getNodeList();
		if (!nodeList.isEmpty())
			this.emptyGraphTest();
	}

	@Test
	public void addNodeNull() {
		assertTrue(Graph.instance.addNode(null) == false);
	}

	@Test
	public void addNodeTrue() {
		assertTrue(Graph.instance.addNode(node1));
		assertTrue(Graph.instance.getNodeList().size() == 1);
	}

	@Test
	public void addNodeContains() {
		Graph.instance.addNode(node1);
		Graph.instance.addNode(node2);
		assertTrue(Graph.instance.addNode(node1) == false);
	}

	@Test
	public void removeNodeTrue() {
		Graph.instance.addNode(node1);
		Graph.instance.addNode(node2);
		Graph.instance.addNode(node3);
		assertTrue(Graph.instance.removeNode(node1));
	}

	@Test
	public void removeNodeContains() {
		Graph.instance.addNode(node2);
		Graph.instance.addNode(node3);
		assertTrue(Graph.instance.removeNode(node1) == false);
	}

	@Test
	public void removeNodeNull() {
		// graph.addNode(node3);
		assertTrue(Graph.instance.removeNode(null) == false);
	}

	@Test
	public void getChildrenTest() {
		Graph.instance.addNode(node1);
		Graph.instance.addNode(node2);
		Node<INodeType> node11 = new Node<INodeType>(new Mock1NodeType());
		Node<INodeType> node12 = new Node<INodeType>(new Mock1NodeType());

		Graph.instance.addNode(node12);
		Graph.instance.addNode(node11);

		List<?> res = Graph.instance.getChildren(Mock1NodeType.class);
		List<Node<INodeType>> exp = new ArrayList<Node<INodeType>>();
		exp.add(node1);
		exp.add(node12);
		exp.add(node11);

		assertEquals(exp, res);

	}

	@Test
	public void getChildrenFail() {
		Graph.instance.addNode(node1);
		Graph.instance.addNode(node2);

		List<?> res = Graph.instance.getChildren(Mock2NodeType.class);
		assertTrue(!res.contains(node1));
	}

	@Test
	public void getChildrenNull() {
		List<?> lst = Graph.instance.getChildren(null);
		assertTrue(lst.isEmpty());
	}

	@Test
	public void getChildren2Test1() {

		Node<INodeType> node111 = new Node<INodeType>(new Mock1NodeType());
		Node<INodeType> node11 = new Node<INodeType>(new Mock1NodeType());

		try {
			Reference<INodeType, INodeType> ref1 = new Reference<INodeType, INodeType>(
					node1, node11);
			node1.addReference(ref1);
			node11.addReference(ref1);
			Reference<INodeType, INodeType> ref2 = new Reference<INodeType, INodeType>(
					node2, node11);
			node2.addReference(ref2);
			node11.addReference(ref2);
			Reference<INodeType, INodeType> ref3 = new Reference<INodeType, INodeType>(
					node1, node111);
			node1.addReference(ref3);
			node111.addReference(ref3);

			Graph.instance.addNode(node1);
			Graph.instance.addNode(node2);
			Graph.instance.addNode(node11);
			Graph.instance.addNode(node111);

			Graph.instance.setTypeClass(Mock1NodeType.class);
			Node<INodeType>[] exp = (Node<INodeType>[]) Graph.instance
					.getChildren();

			Node<INodeType>[] res = new Node[3];
			res[0] = node1;
			res[1] = node11;
			res[2] = node111;

			assertEquals(res, exp);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Test
	public void getChildren2Test2() {

		Node<INodeType> node111 = new Node<INodeType>(new Mock1NodeType());
		Node<INodeType> node11 = new Node<INodeType>(new Mock1NodeType());

		try {
			Reference<INodeType, INodeType> ref1 = new Reference<INodeType, INodeType>(
					node1, node11);
			node1.addReference(ref1);
			node11.addReference(ref1);
			Reference<INodeType, INodeType> ref2 = new Reference<INodeType, INodeType>(
					node2, node11);
			node2.addReference(ref2);
			node11.addReference(ref2);
			Reference<INodeType, INodeType> ref3 = new Reference<INodeType, INodeType>(
					node1, node111);
			node1.addReference(ref3);
			node111.addReference(ref3);

			Graph.instance.addNode(node1);
			Graph.instance.addNode(node2);
			Graph.instance.addNode(node11);
			Graph.instance.addNode(node111);

			Graph.instance.setTypeClass(Mock2NodeType.class);
			Node<INodeType>[] exp = (Node<INodeType>[]) Graph.instance
					.getChildren();

			Node<INodeType>[] res = new Node[1];
			res[0] = node2;

			assertEquals(res, exp);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Test
	public void getChildren2TestNull() {
		Graph.instance.setTypeClass(null);
		assertEquals(null, Graph.instance.getChildren());
	}

	@Test
	public void resetTest() {
		Graph.instance.addNode(node1);
		Graph.instance.addNode(node2);
		Graph.instance.addNode(node3);
		Graph.instance.resetGraph();
		assertTrue(Graph.instance.getChildren() == null);
	}

}
